package handler

import (
	"github.com/gin-gonic/gin"
	ps "lab-service/proto/security"
	"net/http"
	"regexp"
)

type Security struct {
	SecurityClient ps.SecurityService
}

func (s *Security) Cors(ctx *gin.Context) {
	ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
	ctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
	ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, Accept")
	ctx.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")
	if ctx.Request.Method == "OPTIONS" {
		ctx.AbortWithStatus(200)
		return
	}
	ctx.Next()
}

func (s *Security) VerifyJwt(ctx *gin.Context) {
	var jwt string
	switch {
	case ctx.GetHeader("Authorization") != "":
		jwt = ctx.GetHeader("Authorization")
	case ctx.Query("Authorization") != "":
		jwt = ctx.Query("Authorization")
	case ctx.Query("token") != "":
		jwt = ctx.Query("token")
	default:
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	jwt = regexp.MustCompile(`^[\w]+?([\s]| )`).
		ReplaceAllString(jwt, "")

	rsp, err := s.SecurityClient.VerifyJwt(ctx, &ps.SecurityRequest{
		Jwt: jwt,
	})
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusUnauthorized, err)
		return
	}

	ctx.Set("uid", rsp.Uid)
	ctx.Set("role", rsp.Role)
}

func (s *Security) RefreshJwt(ctx *gin.Context) {
	rsp, err := s.SecurityClient.SignJwt(ctx, &ps.SecurityRequest{
		Uid: ctx.Value("uid").(int64),
	})
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}

	ctx.JSON(http.StatusOK, rsp)
}

func (s *Security) Logout(ctx *gin.Context) {
	_, err := s.SecurityClient.ExpireToken(ctx, &ps.SecurityRequest{
		Uid: ctx.Value("uid").(int64),
	})
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}

	ctx.JSON(http.StatusOK, "success")
}

func (s *Security) RoleAdmin(ctx *gin.Context) {
	role := ctx.Value("role").(ps.Role)
	if role != ps.Role_Admin {
		ctx.AbortWithStatus(http.StatusForbidden)
	}
}
